﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CSharpRunner
{

    class MersenneTwister
    {
        const int STATE_SIZE = 624;
	    const int MIDDLE_WORD = 397;
	    const uint DEFAULT_SEED = 5489U;

	    uint[] state = new uint[STATE_SIZE];
	    int position;

        public MersenneTwister()
	    {
		    Seed(DEFAULT_SEED);
	    }

	    public void Seed(uint seed)
	    {
		    state[0] = seed & 0xFFFFFFFFU; 
		    for (uint i = 1; i < STATE_SIZE; ++i) 
		    {
			    state[i] = 1812433253U * (state[i - 1] ^ (state[i - 1] >> 30)) + i;
			    state[i] &= 0xFFFFFFFFU;
		    }
		    position = STATE_SIZE;
	    }

	    public double Next() 
	    {
		    return (double)(NextInt32()) * (1.0 / 4294967296.0);
	    }


	    uint NextInt32()
	    {
		    if (position == STATE_SIZE) 
			    GenerateState();

		    uint x = state[position++];
		    x ^= (x >> 11);
		    x ^= (x << 7) & 0x9D2C5680U;
		    x ^= (x << 15) & 0xEFC60000U;
		    return x ^ (x >> 18);
	    }

	    void GenerateState() 
	    { 
		    for (int i = 0; i < (STATE_SIZE - MIDDLE_WORD); ++i)
			    state[i] = state[i + MIDDLE_WORD] ^ 
				    Twiddle(state[i], state[i + 1]);

		    for (int i = STATE_SIZE - MIDDLE_WORD; i < (STATE_SIZE - 1); ++i)
			    state[i] = state[i + MIDDLE_WORD - STATE_SIZE] ^ 
				    Twiddle(state[i], state[i + 1]);

		    state[STATE_SIZE - 1] = state[MIDDLE_WORD - 1] ^ 
			    Twiddle(state[STATE_SIZE - 1], state[0]);
		    position = 0;
	    }

	    uint Twiddle(uint u, uint v) 
	    {
		    return (((u & 0x80000000U) | (v & 0x7FFFFFFFU)) >> 1) ^ 
			    ((v & 1U) != 0 ? 0x9908B0DFU : 0x0U);
	    }

    };
}
